#include "types.h"
#include "file_system.h"
#include "elf.h"

extern fs_t vFS;

extern int VFSInit(void);
extern void printk(char *fmt, ...);
extern int memncpy(void *srcAddr, void *desAddr, unsigned int nBytes);

#define EXCUTE_ADDR 0x30100000
int excute(unsigned int addr)
{
    asm volatile(
        "mov pc,r0\n\t");

    printk("main returned\n");

    return (0);
}

void excute_test_bin(void)
{
    int ret = -1;
    file_t *pFile = NULL;

    ret = VFSInit();
    if (ret == ERR_RET)
    {
        printk("VFSInit error\n");
        return;
    }
    printk("VFSInit success\n");

    pFile = vFS.NameToInode("user_main.bin");
    if (pFile == NULL)
    {
        printk("vFS.NameToInode error\n");
        return;
    }
    printk("vFS.NameToInode sucess\n");

    ret = memncpy((char *)(vFS.GetDataAddr(pFile)), (char *)EXCUTE_ADDR, pFile->size);
    if (ret == ERR_RET)
    {
        printk("memncpy error\n");
        return;
    }
    printk("memncpy success\n");

    excute(EXCUTE_ADDR);

    return;
}

void excute_test_elf(void)
{
    int ret = -1;
    file_t *pFile = NULL;
    struct elf32_ehdr *pELF32Head = NULL;
    struct elf32_phdr *pELF32ProgramHead = NULL;
    unsigned int i = 0;

    ret = VFSInit();
    if (ret == ERR_RET)
    {
        printk("VFSInit error\n");
        return;
    }
    printk("VFSInit success\n");

    pFile = vFS.NameToInode("user_main.elf");
    if (pFile == NULL)
    {
        printk("vFS.NameToInode error\n");
        return;
    }
    printk("vFS.NameToInode sucess\n");

    pELF32Head = (struct elf32_ehdr *)(vFS.GetDataAddr(pFile));
    pELF32ProgramHead = (struct elf32_phdr *)((char *)pELF32Head + pELF32Head->e_phoff);

    // printk("pELF32Head:%a\n",pELF32Head);
    // printk("vFS.GetDataAddr(pFile):%a\n",vFS.GetDataAddr(pFile));
    // printk("pELF32Head->e_phoff:%a\n",pELF32Head->e_phoff);
    // printk("pELF32ProgramHead:%a\n",pELF32ProgramHead);
    // printk("pELF32Head->e_phnum:%a\n",pELF32Head->e_phnum);

    for (i = 0; i < pELF32Head->e_phnum; i++)
    {
        // printk("i:%a\n",i);
        // printk("pELF32ProgramHead->p_type:%d\n",pELF32ProgramHead->p_type);

        if (pELF32ProgramHead->p_type == PT_LOAD)
        {

            ret = memncpy((char *)pELF32Head + pELF32ProgramHead->p_offset, (char *)(pELF32ProgramHead->p_vaddr), pELF32ProgramHead->p_filesz);
            if (ret == ERR_RET)
            {
                printk("%a,memncpy error\n", i);
                return;
            }
            printk("%a,memncpy success\n", i);
            pELF32ProgramHead++;
        }
    }

    // printk("pELF32Head->e_entry:%a\n",pELF32Head->e_entry);
    excute(pELF32Head->e_entry);

    return;
}